
// LiteLoader-AIDS automatic generated
/// <reference path="c:\Users\Yoyo\AppData\mclib/dts/helperlib/src/index.d.ts"/> 

ll.registerPlugin(
    /* name */ "自定义称号",
    /* introduction */ "一款高自定义的称号插件 | 称号商店",
    /* version */[0, 2, 7],
    /* otherInformation */ {
        author: 'Yoyo'
    }
);


const CONFIG = new JsonConfigFile(".\\plugins\\Yoyo\\NewTitleYoyo\\config.json", JSON.stringify({
    MsgStr: "§l§3[记分板money:{SCOREITEM=money}]§1[{SYSTEM}]§6[{PING}ms]§7[{TIME}]§4{GRANT[0]}{GRANT[1]}§r[{DIMID}] {TITLE} §3{NAME} §r>> {MSG}",
    dimidColor: [
        "§4未知§r",
        "§2主世界§r",
        "§5下界§r",
        "§9末地§r"
    ],
    showToNameStatus: 0,
    showToName: "§l§4{GRANT[0]}{GRANT[1]}§r{TITLE}{NAME}§l§4{HEALTH}",
    score: {
        LLmoney: 1,
        Scores: "记分项名称"
    },
    recycle: {
        status: 0,
        exchange: 50
    },
    TitleList: [
        { title: "<§l§e齐天大圣§r>", price: 10 },
        { title: "<§l§2小萌新§r>", price: 0 },
        { title: "<§l§5牛牛§r>", price: 999999 }
    ],
    language: {
        ScoresError: "积分项不存在!",
        ScoreNot: "不够!",
        succeed: "操作成功",
        failure: "操作失败!!!",
        noContent: "没有内容!!",
        HomeMenuTitle: "称号管理",
        HomeMenuBtn1: "称号商店",
        HomeMenuBtn2: "我的称号",
        shopPutaway: "已上架",
        shopSelect: "§l§4取消 §r<==> §l§2购买",
        titleOwned: "称号已拥有",
        titleNot: "没有称号",
        free: "免费",
        none: "无",
        MyMsg: {
            Mytitle: "我的称号",
            titleList: "称号列表",
            wear: "佩戴",
            sellTitle: "回收出售",
            wearSelect: [
                "§l§4取消",
                "§l§2佩戴",
                "§l§3回收"
            ],
            TheCurrentWear: "当前佩戴 : ",
            RecycleStatusNo: "当前管理不允许回收称号",
            Recycle: "是否以汇率 百分之§l§2[{EXCHANGE}]§r 回收当前称号 你可以得到 §l§4[{SCORE}]",
            RecycleBtn: [
                "回收",
                "算了太坑了"
            ]
        },
        manageMsg: {
            title: "称号后台管理",
            grantTitle: "选择赐予玩家",
            grantList: "该玩家授予称号列表",
            selectBack: "返回 <==> 下一步",
            select: [
                "新添加一个授予称号",
                "删除已有授予称号",
                "修改已有授予称号时间"
            ],
            backSelect: {
                add: "取消 <==> 添加",
                del: "取消 <==> 删除",
                upDate: "取消 <==> 修改"
            },
            oneself: "自己",
            civilian: "玩家",
            TitleGrant: "请输入需要赐予的称号",
            expire: "有效小时",
            shop: "称号商店",
            GivenTheTitle: "赐予称号",
            ShopTitle: "请选择",
            shopAdd: "添加商品",
            shopDel: "删除商品",
            shopRecycle: "商店回收设置",
            shopRecycleRate: "商店回汇率和是否开放回收",
            currentExchange: "当前汇率",
            recycleStatus: "当前是否开放回收"

        }
    }
}));

let AddVar = {};

const DB = new KVDatabase(".\\plugins\\Yoyo\\NewTitleYoyo\\database");
var path = ".\\plugins\\Yoyo\\NewTitleYoyo\\filtration.csv";
logger.setTitle("Sensitive");
if (!File.exists(path)) {
    File.writeTo(path, "nmb,0");
}
let config = File.readFrom(path);
if (config == null) {
    logger.warn("Configuration file empty detected");
}
let CONFIGLIST = Configuration(config);
let plchar = {};


class NTL {
    #error = "";
    #language = {};
    #selectXuid;
    constructor() {
        this.#language = CONFIG.get("language");
    }

    utwPlTiGuiMenu(player) {
        let utw = mc.newSimpleForm();
        utw.setTitle(this.#language.HomeMenuTitle);
        utw.addButton(this.#language.HomeMenuBtn1);
        utw.addButton(this.#language.HomeMenuBtn2);
        player.sendForm(utw, (player, id) => {
            if (id == null && id !== 0) return;
            if (id === 0) {
                this.utwTlTitleShop(player);
            } else {
                this.utwPlMyTitle(player);
            }
        });
    }

    utwPlMyTitle(player) {//个人称号
        let titleList = DB.get(player.xuid);
        if (titleList == null) {
            titleList = {
                wear: 0,
                title: [
                ],
                grant: [

                ]
            }
        }
        let utw = mc.newCustomForm();
        utw.setTitle(this.#language.MyMsg.Mytitle);
        utw.addLabel(this.#language.MyMsg.TheCurrentWear + (titleList.title[titleList.wear] ? titleList.title[titleList.wear].title : this.#language.none));
        let titArr = titleList.title.map((a) => a.title + "§r |  §l§4:" + (a.price || this.#language.free) + "§r");
        utw.addDropdown(this.#language.MyMsg.titleList, titArr);
        utw.addStepSlider('select:', this.#language.MyMsg.wearSelect, 1);
        player.sendForm(utw, (player, datas) => {
            if (datas == null) return;
            if (datas[2] == 0) {
                this.utwPlTiGuiMenu(player);
            } else if (datas[2] == 1) {
                this.theTitleOfWear(player, datas[1]);
                this.showToName(player.xuid);
                this.utwBack(player, this.#language.succeed, "utwPlMyTitle");
            } else {
                //回收
                if (CONFIG.get("recycle").status != 1) {
                    this.utwBack(player, this.#language.MyMsg.RecycleStatusNo, "utwPlMyTitle");
                    return;
                }
                let exc = parseInt(CONFIG.get("recycle").exchange);
                let titlePrice = parseInt(titleList.title[datas[1]].price);
                let conten = this.#language.MyMsg.Recycle;
                let RecycleRrice = parseInt((exc / 100) * titlePrice);
                conten = conten.replace('{EXCHANGE}', exc);
                conten = conten.replace('{SCORE}', RecycleRrice);
                player.sendModalForm(this.#language.MyMsg.sellTitle, conten, this.#language.MyMsg.RecycleBtn[0], this.#language.MyMsg.RecycleBtn[1], (player, result) => {
                    if (result == null && result != 0) return;
                    if (result == 1) {
                        if (this.ScoreOperation(player, RecycleRrice, "add")) {
                            titleList.title.splice(datas[1], 1);
                            DB.set(player.xuid, titleList); 776
                            this.utwBack(player, this.#language.succeed, "utwPlMyTitle");
                            return;
                        } else {
                            this.utwBack(player, this.#language.failure, "utwPlMyTitle");
                            return;
                        }
                    } else {
                        this.utwPlMyTitle(player);
                    }
                });
            }
        });
        //个人称号
    }

    utwTlTitleShop(player) {//称号商店
        let titleList = CONFIG.get("TitleList");
        let utw = mc.newCustomForm();
        utw.setTitle(this.#language.HomeMenuBtn1);
        let titArr = titleList.map((a) => a.title + "§r |  §l§4:" + (a.price || this.#language.free) + "§r");
        utw.addDropdown(this.#language.shopPutaway, titArr);
        utw.addSwitch(this.#language.shopSelect, true);
        player.sendForm(utw, (player, datas) => {
            if (datas == null) return;
            if (datas[1] == 0) {
                this.utwPlTiGuiMenu(player);
            } else {
                let plTitleOb = DB.get(player.xuid);
                if (plTitleOb == null) {
                    plTitleOb = {
                        wear: 0,
                        title: [
                        ],
                        grant: [

                        ]
                    }
                }
                //判断是否拥有
                let isContain = plTitleOb.title.filter(a => a.title == titleList[datas[0]].title);
                if (isContain.length > 0) {
                    this.#error = this.#language.titleOwned;
                    this.utwBack(player, this.#error, "utwTlTitleShop");
                    return;
                }
                let PayResult = this.ScoreOperation(player, titleList[datas[0]].price, "reduce");
                if (!PayResult) {
                    this.utwBack(player, this.#error, "utwTlTitleShop");
                    return;
                }
                //购买成功
                plTitleOb.title.push(titleList[datas[0]]);
                DB.set(player.xuid, plTitleOb);
                this.utwBack(player, this.#language.succeed, "utwTlTitleShop");

            }
        });
        //称号商店
    }

    utwBack(player, txt, PageName) {
        player.sendModalForm("§l§5Message", txt, "back", "exit", (player, result) => {
            if (result != 0) {
                this[PageName](player);
            }
        });
    }

    ScoreOperation(pl, sum, type = "add") {
        let scoreType = CONFIG.get("score");

        if (scoreType.LLmoney == 1) {
            if (type != "add" && money.get(pl.xuid) < sum) {
                this.#error = this.#language.ScoreNot;
                return false;
            }
            if (type == "add") {
                return money.add(pl.xuid, Math.abs(sum));
            } else {
                return money.reduce(pl.xuid, Math.abs(sum));
            }
        } else {
            if (!mc.getScoreObjective(scoreType.Scores)) {
                colorLog("red", "[NewTitle]" + this.#language.ScoresError)
                this.#error = this.#language.ScoresError;
                return false;
            }
            if (type != "add" && pl.getScore(scoreType.Scores) < sum) {
                this.#error = this.#language.ScoreNot;
                return false;
            }
            if (type == "add") {
                return pl.addScore(scoreType.Scores, Math.abs(sum));
            } else {
                return pl.reduceScore(scoreType.Scores, Math.abs(sum));
            }

        }
        // return true;
    }

    initPlayer(xuid) {
        let titleList = DB.get(xuid);
        if (titleList == null) {
            //初始化和发放新称号
            titleList = {
                wear: 0,
                title: [
                ],
                grant: [

                ]
            }
            DB.set(xuid, titleList);
        }
    }

    theTitleOfWear(player, index) {//佩戴选择的
        let titleList = DB.get(player.xuid);
        if (titleList == null) {
            this.initPlayer(player.xuid);
        }
        if (titleList.title[index]) {
            titleList.wear = index;
            DB.set(player.xuid, titleList);
        }
    }

    showToName(xuid) {//{GRANT[0]} <{TITLE}><{NAME}><{HEALTH}>
        if (!CONFIG.get("showToNameStatus")) return;//关闭改名称
        let pl = mc.getPlayer(xuid);
        let pastCount = 0;
        if (!pl) return;//不在线
        let titleList = DB.get(xuid);
        let showToNameC = CONFIG.get("showToName");
        if (titleList == null) {
            this.initPlayer(xuid);
        }
        titleList.grant.forEach((v1, k1) => {
            if (v1.time < parseInt(new Date().getTime() / 1000)) {
                titleList.grant.splice(k1, 1);
                pastCount++;
            }
        });
        if (pastCount > 0) {
            DB.set(xuid, titleList);
        }
        let seCount = showToNameC.match(/{GRANT\[\d+\]}/g);
        if (seCount == null) {
            showToNameC = showToNameC.replace(/{GRANT\[\d+\]}/g, '');
        } else {

            seCount.forEach((v, k) => {//替换赐予称号
                if (titleList.grant[k] instanceof Object) {
                    showToNameC = showToNameC.replace(v, titleList.grant[k].title);
                } else {
                    showToNameC = showToNameC.replace(v, '');
                }
            });
        }

        showToNameC = showToNameC.replace(/{(bep|b)=([^}\n\s:]+)(:pl|:player)?}/g, (...ages) => {
            let repData = '';
            if (isBEP) {
                if (/:(player|pl)$/i.test(ages[3])) {
                    // 玩家变量
                    repData = PAPI.getValueByPlayer(ages[2], xuid);
                } else {
                    // 服务器变量
                    repData = PAPI.getValue(ages[2]);
                }
            } else {
                repData = '{NoBep}';
            }
            return repData;
        });//替换玩家bep的变量

        showToNameC = showToNameC.replace(/{TITLE}/g, titleList.title[titleList.wear] ? titleList.title[titleList.wear].title : '');//替换自带称号
        showToNameC = showToNameC.replace(/{NAME}/g, data.xuid2name(xuid));//替换玩家名称

        showToNameC = showToNameC.replace(/{HEALTH}/g, pl.health);//替换玩家当前血量

        /*  let ScoresName = "YoyoNewTitle";
         mc.removeScoreObjective(ScoresName)
         let ScoreObj = mc.newScoreObjective(ScoresName,showToNameC);
         mc.runcmdEx("scoreboard objectives setdisplay belowname");
         pl.setScore(ScoresName,0);
         mc.runcmdEx("scoreboard objectives setdisplay belowname "+ScoresName); */

        pl.rename(showToNameC);//改名
    }

    showToTitle(player, msg) {//{GRANT[0]} [{TIME}][{DIMID}]<{TITLE}><{NAME}> {MSG}
        let titleList = DB.get(player.xuid);
        let showToTitleC = CONFIG.get("MsgStr");
        if (titleList == null) {
            this.initPlayer(player.xuid);
        }
        let seCount = showToTitleC.match(/{GRANT\[\d+\]}/g);
        if (seCount == null) {
            showToTitleC = showToTitleC.replace(/{GRANT\[\d+\]}/g, '');
        } else {
            let pastCount = 0;
            // 先过滤一遍过期的
            titleList.grant.forEach((v1, k1) => {
                if (v1.time < parseInt(new Date().getTime() / 1000)) {
                    titleList.grant.splice(k1, 1);
                    pastCount++;
                }
            });
            if (pastCount > 0) {
                DB.set(player.xuid, titleList);
            }

            seCount.forEach((v, k) => {//替换赐予称号
                if (titleList.grant[k] instanceof Object) {
                    showToTitleC = showToTitleC.replace(v, titleList.grant[k].title);
                } else {
                    showToTitleC = showToTitleC.replace(v, '');
                }
            });
        }

        showToTitleC = showToTitleC.replace(/{TITLE}/g, titleList.title[titleList.wear] ? titleList.title[titleList.wear].title : '');//替换自带称号
        showToTitleC = showToTitleC.replace(/{NAME}/g, data.xuid2name(player.xuid));//替换玩家名称
        showToTitleC = showToTitleC.replace(/{HEALTH}/g, player.health);//替换玩家当前血量
        showToTitleC = showToTitleC.replace(/{DIMID}/g, this.selectDimidColor(`${player.pos.dimid}`));//替换玩家当前维度
        let date = system.getTimeObj();
        showToTitleC = showToTitleC.replace(/{TIME}/g, date.h + ":" + (date.m < 10 ? '0' + date.m : date.m) + ":" + (date.s < 10 ? '0' + date.s : date.s));//替换玩家当前时间
        let Device = player.getDevice();
        showToTitleC = showToTitleC.replace(/{PING}/g, `${Device.avgPing}`);//替换玩家当前延迟
        showToTitleC = showToTitleC.replace(/{SYSTEM}/g, `${Device.os}`);//替换玩家当前客户端
        showToTitleC = showToTitleC.replace(/{SCOREITEM=([^}\n\s]+)}/g, (...ages) => player.getScore(ages[1]));//替换玩家当前积分项分数
        //自定义变量
        let varKey = Object.keys(AddVar);
        if (varKey.length >= 1) {
            varKey.forEach(vval => {
                let regularx = RegExp(`{${vval}}`, 'g');
                try {
                    let varsi2 = AddVar[vval](player.xuid);
                    if (varsi2 == null) varsi2 = '';
                    showToTitleC = showToTitleC.replace(regularx, varsi2);
                } catch (error) {
                    logger.error(`${vval} 这个注册方法不存在 请联系注入的开发者,这个和称号插件无关!`);
                }
            });
        }

        showToTitleC = showToTitleC.replace(/{(bep|b)=([^}\n\s:]+)(:pl|:player)?}/g, (...ages) => {
            let repData = '';
            if (isBEP) {
                if (/:(player|pl)$/i.test(ages[3])) {
                    // 玩家变量
                    repData = PAPI.getValueByPlayer(ages[2], player.xuid);
                } else {
                    // 服务器变量
                    repData = PAPI.getValue(ages[2]);
                }
            } else {
                repData = '{NoBep}';
            }
            return repData;
        });//替换玩家bep的变量

        msg = msg.replace(/^(@.+) (.+)/g, "§l§4To§r $1 >> $2");
        showToTitleC = showToTitleC.replace(/{MSG}/g, msg);//替换玩家当前聊天信息
        return showToTitleC;
    }

    selectDimidColor(index) {
        let Color = CONFIG.get("dimidColor");
        let key = 0;
        switch (index) {
            case "-1":
                key = 0;
                break;
            case "0":
                key = 1;
                break;
            case "1":
                key = 2;
                break;
            case "2":
                key = 3;
                break;
        }
        return Color[key];
    }

    manageMenu(player) {
        let utw = mc.newSimpleForm();
        utw.setTitle(this.#language.manageMsg.title);
        utw.addButton(this.#language.manageMsg.shop);
        utw.addButton(this.#language.manageMsg.GivenTheTitle);
        player.sendForm(utw, (player, id) => {
            if (id == null && id !== 0) return;
            if (id == 0) {
                this.shopMenu(player);
            } else if (id == 1) {
                this.openManageGui(player);
            }
        });
    }
    shopMenu(player) {
        let utw = mc.newSimpleForm();
        utw.setTitle(this.#language.manageMsg.ShopTitle);
        utw.addButton(this.#language.manageMsg.shopAdd);
        utw.addButton(this.#language.manageMsg.shopDel);
        utw.addButton(this.#language.manageMsg.shopRecycle);
        player.sendForm(utw, (player, id) => {
            if (id == null && id !== 0) return;
            if (id == 0) {
                this.shopAddItem(player);
            } else if (id == 1) {
                this.shopDelItem(player);
            } else {
                this.RecycleSet(player);
            }
        });
    }
    shopAddItem(player) {
        let TitleLists = CONFIG.get("TitleList");
        let utw = mc.newCustomForm();
        utw.setTitle(this.#language.manageMsg.shopAdd);
        utw.addInput("Title:");
        utw.addInput("price:");
        utw.addSwitch(this.#language.manageMsg.backSelect.add, true);
        player.sendForm(utw, (player, datas) => {
            if (datas == null) return;
            if (datas[2] != 1) {
                this.shopMenu(player);
                return;
            }
            let repetition = TitleLists.filter(a => a.title == datas[0]);
            if (repetition > 0) {
                this.utwBack(player, this.#language.titleOwned, "shopAddItem");
                return;
            }
            if (!/^\d+$/.test(datas[1])) {
                this.utwBack(player, "The price can only be a number!!", "shopAddItem");
                return;
            }
            TitleLists.push({ title: datas[0], price: parseInt(datas[1]) });
            CONFIG.set("TitleList", TitleLists);
            CONFIG.reload();
            this.utwBack(player, this.#language.succeed, "shopAddItem");
        });
    }

    shopDelItem(player) {
        let TitleLists = CONFIG.get("TitleList");
        let utw = mc.newCustomForm();
        utw.setTitle(this.#language.manageMsg.shopDel);
        let showTitleLists = TitleLists.map((a) => a.title + "§r |  §l§4:" + (a.price || this.#language.free) + "§r");
        utw.addDropdown("Select:", showTitleLists);
        utw.addSwitch(this.#language.manageMsg.backSelect.del, true);
        player.sendForm(utw, (player, datas) => {
            if (datas == null) return;
            if (datas[1] != 1) {
                this.shopMenu(player);
                return;
            }
            TitleLists.splice(datas[0], 1);
            CONFIG.set("TitleList", TitleLists);
            CONFIG.reload();
            this.utwBack(player, this.#language.succeed, "shopDelItem");
        });
    }

    RecycleSet(player) {
        let configEx = CONFIG.get("recycle");
        let utw = mc.newCustomForm();
        utw.setTitle(this.#language.manageMsg.shopRecycle);
        utw.addSlider(this.#language.manageMsg.currentExchange, 1, 100, 1, parseInt(configEx.exchange));
        utw.addSwitch(this.#language.manageMsg.recycleStatus, configEx.status ? true : false);
        player.sendForm(utw, (player, datas) => {
            if (datas == null) return;
            configEx.exchange = datas[0];
            configEx.status = datas[1];
            CONFIG.set("recycle", configEx);
            CONFIG.reload();
            this.utwBack(player, this.#language.succeed, "shopMenu");
        });
    }

    openManageGui(player) {
        let utw = mc.newSimpleForm();
        utw.setTitle(this.#language.manageMsg.grantTitle);
        let plList = mc.getOnlinePlayers();
        plList.forEach((v, k) => {
            utw.addButton((player.xuid == v.xuid ? '§2(' + this.#language.manageMsg.oneself + ')' + data.xuid2name(v.xuid) : `(${this.inIdentity(v)})` + data.xuid2name(v.xuid)));
        });
        player.sendForm(utw, (player, id) => {
            if (id == null && id !== 0) return;
            this.#selectXuid = plList[id].xuid;
            this.selectManageGui(player);
        });
    }

    selectManageGui(player) {
        let xuid = this.#selectXuid;
        let utw = mc.newCustomForm();
        utw.setTitle(data.xuid2name(xuid));
        utw.addDropdown("select", this.#language.manageMsg.select);
        utw.addSwitch(this.#language.manageMsg.selectBack, true);
        player.sendForm(utw, (player, datas) => {
            if (datas == null) return;
            if (datas[1] != 1) {
                this.openManageGui(player);
                return;
            }
            if (datas[0] == 1) {
                this.deleteTheTitle(player);
            } else if (datas[0] == 0) {
                this.addTheTitle(player);
            } else {
                this.upDateTheTitle(player);
            }
        });
    }

    deleteTheTitle(player) {
        let xuid = this.#selectXuid;
        let grantList = DB.get(xuid);
        let pastCount = 0;
        grantList.grant.forEach((v1, k1) => {
            if (v1.time < parseInt(new Date().getTime() / 1000)) {
                grantList.grant.splice(k1, 1);
                pastCount++;
            }
        });
        if (pastCount > 0) {
            DB.set(xuid, grantList);
        }
        let utw = mc.newCustomForm();
        utw.setTitle(data.xuid2name(xuid));
        let granShow = grantList.grant.map((a) => a.title + " | " + Number(((a.time - parseInt(new Date().getTime() / 1000)) / 60 / 60).toFixed(2)));
        utw.addDropdown("select", granShow);
        utw.addSwitch(this.#language.manageMsg.backSelect.del, true);
        player.sendForm(utw, (player, datas) => {
            if (datas == null) return;
            if (datas[1] == 0) {
                this.selectManageGui(player);
            } else {
                if (grantList.grant.length < 1) {//没有
                    this.utwBack(player, this.#language.titleNot, "deleteTheTitle");
                } else {
                    grantList.grant.splice(datas[0], 1);
                    DB.set(xuid, grantList);
                    this.showToName(xuid);
                    this.utwBack(player, this.#language.succeed, "deleteTheTitle");
                }
            }
        });
    }

    upDateTheTitle(player) {
        let xuid = this.#selectXuid;
        let grantList = DB.get(xuid);
        let pastCount = 0;
        grantList.grant.forEach((v1, k1) => {
            if (v1.time < parseInt(new Date().getTime() / 1000)) {
                grantList.grant.splice(k1, 1);
                pastCount++;
            }
        });
        if (pastCount > 0) {
            DB.set(xuid, grantList);
        }
        let utw = mc.newCustomForm();
        utw.setTitle(data.xuid2name(xuid));
        let granShow = grantList.grant.map((a) => a.title + " | " + Number(((a.time - parseInt(Date.now()/1000)) / 60 / 60).toFixed(2)));
        utw.addDropdown("select", granShow);
        utw.addSlider(this.#language.manageMsg.expire, 1, 9999, 1, 1);
        utw.addSwitch(this.#language.manageMsg.backSelect.upDate, true);
        player.sendForm(utw, (player, datas) => {
            if (datas == null) return;
            if (datas[2] == 0) {
                this.selectManageGui(player);
            } else {
                if (grantList.grant.length < 1) {//没有
                    this.utwBack(player, this.#language.titleNot, "upDateTheTitle");
                } else {
                    grantList.grant[datas[0]].time = parseInt(datas[1]);
                    DB.set(xuid, grantList);
                    this.utwBack(player, this.#language.succeed, "upDateTheTitle");
                }
            }
        });
    }

    addTheTitle(player) {
        let xuid = this.#selectXuid;
        let grantList = DB.get(xuid);
        let utw = mc.newCustomForm();
        utw.setTitle(data.xuid2name(xuid));
        utw.addInput('', this.#language.manageMsg.TitleGrant);
        utw.addSlider(this.#language.manageMsg.expire, 1, 9999, 1, 720);
        utw.addSwitch(this.#language.manageMsg.backSelect.add, true);
        player.sendForm(utw, (player, datas) => {
            if (datas == null) return;
            if (datas[2] != 1) {
                this.selectManageGui(player);
                return;
            }
            if (datas[0] == '') {
                this.utwBack(player, this.#language.noContent, "addTheTitle");
                return;
            }
            let bohArr = grantList.grant.filter(a => a.title == datas[0]);
            if (bohArr.length > 0) {
                this.utwBack(player, this.#language.titleOwned, "addTheTitle");
                return;
            }
            grantList.grant.push({ title: datas[0], time: parseInt(new Date().getTime() / 1000) + (60 * 60 * parseInt(datas[1])) });
            DB.set(xuid, grantList);
            this.utwBack(player, this.#language.succeed, "addTheTitle");
            this.showToName(xuid);
        });
    }
    inIdentity(player) {
        if (player.isOP()) {
            return "§l§4OP§r";
        }
        return this.#language.manageMsg.civilian;
    }
}



mc.listen("onChat", onChat);
mc.listen("onJoin", onJoin);
mc.listen("onServerStarted", onServerStarted);
const isBEP = ll.hasExported("BEPlaceholderAPI", "GetValue");
let PAPI = null;
Function.prototype.getName = function () {
    return this.name || this.toString().match(/function\s*([^(]*)\(/)[1];
}
if (isBEP) {
    // 自己引入 防止删除 BEPlaceholderAPI.dll 然后库还在导致的问题
    PAPI = {
        getValue: ll.import("BEPlaceholderAPI", "GetValue"),
        getValueByPlayer: ll.import("BEPlaceholderAPI", "GetValueWithPlayer"),
        PAPIregisterServerPlaceholderAPI: ll.import("BEPlaceholderAPI", "registerServerPlaceholder"),
        PAPIregisterPlayerPlaceholderAPI: ll.import("BEPlaceholderAPI", "registerPlayerPlaceholder"),
        PAPIregisterStaticPlaceholderAPI: ll.import("BEPlaceholderAPI", "registerStaticPlaceholder"),
        registerServerPlaceholder(func, PluginName, PAPIName) {
            ll.export(func, PluginName, func.getName());
            this.PAPIregisterServerPlaceholderAPI(PluginName, func.getName(), PAPIName);
        },
        registerPlayerPlaceholder(func, PluginName, PAPIName) {

            ll.export(func, PluginName, func.getName());
            this.PAPIregisterPlayerPlaceholderAPI(PluginName, func.getName(), PAPIName);
        },
        registerStaticPlaceholder(func, PluginName, PAPIName, UpdateInterval) {
            ll.export(func, PluginName, func.getName());
            this.PAPIregisterStaticPlaceholderAPI(PluginName, func.getName(), PAPIName, UpdateInterval);
        },
        translateString: ll.import("BEPlaceholderAPI", "translateString"),
        unRegisterPlaceholder: ll.import("BEPlaceholderAPI", "unRegisterPlaceholder"),

    };
}


function regCmd() {
    const cmd = mc.newCommand("tl", "-称号管理", PermType.Any);
    cmd.setEnum("ChangeAction", ["manage", "siv"]);
    cmd.setEnum("alteration", ["add"]);
    cmd.setEnum("alterationgrant", ["addgrant"]);
    cmd.mandatory("action", ParamType.Enum, "ChangeAction", 1);
    cmd.mandatory("action", ParamType.Enum, "alteration", 1);
    cmd.mandatory("action", ParamType.Enum, "alterationgrant", 1);
    cmd.optional("default", ParamType.Bool);
    cmd.mandatory("player", ParamType.Player);
    cmd.mandatory("title", ParamType.String);
    cmd.optional("price", ParamType.Int);
    cmd.mandatory("time", ParamType.Int);
    cmd.optional("isWear", ParamType.Bool);
    cmd.overload(["ChangeAction"]);
    cmd.overload(["default"]);
    cmd.overload(["alteration", "player", "title","price"]);
    cmd.overload(["alterationgrant", "player", "title","time"]);
    cmd.setCallback((_cmd, _ori, out, res) => {
        let pl = _ori.player;
        if (res.action && res.action == 'manage' && pl == null) {
            // 这个不能
            return out.error("\\" + res.action + " 该命令只能玩家执行！");
        }
        switch (res.action) {
            case "manage":
                if(!pl.isOP()) out.error("你没有权限执行！");
                return OpTl(pl);
            case "siv":
                if(pl!=null&&!pl.isOP()) out.error("你没有权限执行！");
                let reloadsiv = (player) => {
                    if (!File.exists(path)) {
                        File.writeTo(path, "n\s*m\s*b,0");
                    }
                    config = File.readFrom(path);
                    if (config == null) {
                        return { status: false, msg: "Configuration file empty detected" }
                    }
                    CONFIGLIST = Configuration(config);
                    return { status: true, msg: "§l§2success!" }
                }
                let resulta = reloadsiv(pl);
                if (resulta.status) {
                    return out.success(resulta.msg);
                }
                return out.error(resulta.msg);
            case "add":
                // 添加一个称号
                if(pl!=null&&!pl.isOP()) out.error("你没有权限执行！");
                let addTitle = () => {
                    for (let p of res.player) {
                        let titleList = DB.get(p.xuid);
                        let isContain = titleList.title.findIndex(a => a.title == res.title);
                        if (isContain !== -1) continue;//判断是否拥有
                        titleList.title.push({ title: res.title,price:res.price==null?0:res.price });
                        if(res.isWear){
                            // 佩戴（默认佩戴）
                            let pindex = titleList.title.length-1;
                            titleList.wear = pindex;
                        }
                        DB.set(p.xuid,titleList);
                    }
                }
                addTitle();
                return out.success(`Add ${res.player.length} titles`);
            case "addgrant":
                // 新增赐予称号
                if(pl!=null&&!pl.isOP()) out.error("你没有权限执行！");
                let addgrant = () => {
                    for (let p of res.player) {
                        let titleList = DB.get(p.xuid);
                        let isContain = titleList.grant.findIndex(a => a.title == res.title);
                        if (isContain !== -1) continue;//判断是否拥有
                        let times = Number(res.time)==NaN?0:parseInt(res.time);
                        titleList.grant.push({ title: res.title,time:parseInt(Date.now()/1000)+times });
                        DB.set(p.xuid,titleList);
                    }
                }
                addgrant();
                return out.success(`Add ${res.player.length} grant titles`);
            default:
                if(pl==null){
                    return out.error("该命令只能玩家执行！");
                }
                return plTl(pl);
        }
    });
    cmd.setup();
}

function onChat(player, msg) {//玩家聊天
    plchar[player.xuid] = { status: true, msg: '' };
    for (let item in CONFIGLIST) {
        if (CONFIGLIST[item][1] == "1") {
            arrFilter(player, msg, CONFIGLIST[item][0]);
        } else {
            oneFilter(player, msg, CONFIGLIST[item][0]);
        }

    }
    if (!plchar[player.xuid].status) {
        msg = plchar[player.xuid].msg;
    }
    let GuiNTL = new NTL();
    GuiNTL.showToName(player.xuid);
    let NewMsg = GuiNTL.showToTitle(player, msg);
    mc.broadcast(NewMsg);
    return false;
}

function onJoin(player) {//玩家进入游戏
    let GuiNTL = new NTL();
    GuiNTL.initPlayer(player.xuid);
    GuiNTL.showToName(player.xuid);
}

function plTl(player, args) {//玩家打开管理
    let GuiNTL = new NTL();
    GuiNTL.utwPlTiGuiMenu(player);
}

function OpTl(player, args) {//op打开后台
    let GuiNTL = new NTL();
    GuiNTL.manageMenu(player);
}


function onServerStarted() {

    regCmd();

    colorLog("green", "[Yoyo] The title plug-in is loaded! (v0.2.6)")
    if (CONFIG.get("showToNameStatus")) {
        setInterval(() => {
            belowName();
        }, 500);
    }
}

function belowName() {
    try {
        var list = mc.getOnlinePlayers();
        for (var i in list) {
            var pl = list[i];
            let GuiNTL = new NTL();
            GuiNTL.showToName(pl.xuid);
        }
    } catch (_) { }
};


function arrFilter(player, msg, se) {
    let sse = new RegExp(se, "g");
    if (sse.test(msg)) {
        plchar[player.xuid].status = false;
        plchar[player.xuid].msg = "***";
        return;
    }
}

function oneFilter(player, msg, se) {
    let sse = new RegExp(se, "g");
    if (sse.test(msg)) {
        plchar[player.xuid].status = false;
        plchar[player.xuid].msg = msg.replace(sse, '***');
        return;
    }
}

function Configuration(config) {
    var SensitiveArr = [];
    let arrStrm = config.split("\n");
    arrStrm.forEach(a => SensitiveArr.push(a.split(",")));
    return SensitiveArr;
}

// AddVar

function title_add(key, funName) {
    if (typeof key != "string" || !/^.{1,20}$/.test(key)) {
        return { code: 400, msg: '请提交正确的key' };
    }
    if (typeof funName != "string") {
        return { code: 400, msg: '请提交正确的funName' };
    }

    try {
        AddVar[`title_${key}`] = lxl.import(funName);
    } catch (error) {
        colorLog('red', `[NewTitle] ${funName} 这个调用不存在`);
        return { code: 404, msg: `${funName} 这个调用不存在` };
    }
    return { code: 200, msg: '变量更新/添加成功' };
}

function title_del(key) {
    if (typeof key != "string" || !/^.{1,20}$/.test(key)) {
        return { code: 400, msg: '字符串不符合规则' };
    }
    if (typeof AddVar[`title_${key}`] == "undefined") {
        return { code: 400, msg: `${key}不存在` };
    }
    delete AddVar[`title_${key}`];
    return { code: 200, msg: '变量删除' };
}
//导出
lxl.export(title_add, 'title_addvar');
lxl.export(title_del, 'title_delvar');
